package com.weixing.mall.core.interceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.weixing.mall.base.constant.GlobalConstant;
import com.weixing.mall.base.utils.AuthCryptoUtil;
import com.weixing.mall.base.wrapper.Result;
import com.weixing.mall.base.wrapper.ResultUtil;
import com.weixing.mall.core.annotation.NoNeedAccess;
import com.weixing.mall.core.support.auth.AgentAuth;
import com.weixing.mall.core.support.auth.MemAuth;
import com.weixing.mall.core.support.auth.SysAuth;
import com.weixing.mall.core.support.auth.AuthDto;
import com.weixing.mall.util.ThreadLocalMap;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

/**
 * 频率限制拦截器
 * <p>
 * The class Token interceptor.
 *
 * @author kfc
 */
@Slf4j
public class AuthInterceptor implements HandlerInterceptor {

    @Resource
    private ObjectMapper objectMapper;


    private boolean needAccess = false;

    /**
     * Pre handle boolean.
     *
     * @param request  the request
     * @param response the response
     * @param handler  the handler
     * @return the boolean
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String requestURI = request.getRequestURI();
        if (log.isDebugEnabled()) {
            log.debug("拦截地址：" + requestURI);
        }
        boolean b = requestURI.startsWith("/doc");
        if (b){
            return true;
        }
        boolean isRpcRequest = requestURI.startsWith("/api");
        // rpc 调用直接放过请求
        if (!isRpcRequest) {
            NoNeedAccess noNeedAccessAnno = getNoNeedAccessAnno(handler);
            this.needAccess = needAccess(noNeedAccessAnno);
            if (this.needAccess || (noNeedAccessAnno.needParseToken())) {
                return parseAuthDto(request, response);
            }
        }
        return true;
    }

    private boolean parseAuthDto(HttpServletRequest request, HttpServletResponse response) {
        // 用户角色
        String ur = request.getHeader(GlobalConstant.X_HEADER_UR);
        // 用户敏感信息
        String uk = request.getHeader(GlobalConstant.X_HEADER_UK);


//        System.out.println("ur:" + ur );
        if (StringUtil.isBlank(uk) || StringUtil.isBlank(ur)) {
            if (this.needAccess) {
                sendResponse(response, ResultUtil.unauthorized("您已登出，请重新登录系统！"));
                return false;
            }
        }
        uk = AuthCryptoUtil.decrypt(uk);
        AuthDto authDto = new AuthDto();
        authDto.setUserRole(ur);
        try {
            if (GlobalConstant.UserRole.MEMBER.equals(ur)) {
                MemAuth memberExt = objectMapper.readValue(uk, MemAuth.class);
                authDto.setMemberExt(memberExt);
                authDto.setUserId(memberExt.getMid());
            } else if (GlobalConstant.UserRole.SYS.equals(ur)){
                SysAuth sysExt = objectMapper.readValue(uk, SysAuth.class);
                authDto.setSysExt(sysExt);
                authDto.setUserId(sysExt.getUid());
            } else if (GlobalConstant.UserRole.AGENT.equals(ur)){
                AgentAuth agentExt = objectMapper.readValue(uk, AgentAuth.class);
                authDto.setAgentExt(agentExt);
                authDto.setUserId(agentExt.getAid());
            }
        } catch (IOException e) {
            log.warn("Auth拦截器异常", e);
        }
        ThreadLocalMap.put(GlobalConstant.TLMK_USER_AUTH_DTO, authDto);
        return true;
    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        ThreadLocalMap.remove(GlobalConstant.TLMK_USER_AUTH_DTO);
    }


    private NoNeedAccess getNoNeedAccessAnno(Object handler) {
        NoNeedAccess access = null;
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            access = handlerMethod.getMethodAnnotation(NoNeedAccess.class);
        }
        return access;
    }


    private boolean needAccess(NoNeedAccess noNeedAccess) {
        return null == noNeedAccess;
    }

    private void sendResponse(HttpServletResponse response, Result result) {
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=UTF-8");
        try (OutputStream out = response.getOutputStream();
             PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, "utf-8"))) {
            // 返回json格式的提示
            pw.println(objectMapper.writeValueAsString(result));
        } catch (IOException ex) {
            log.warn("", ex);
        }
    }
}
